package com.manong.config.redis;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;

/**
 * Redis配置
 * @author 李茂鑫
 * @Date 2025/1/15 9:01
 * @Descripition
 */
@Configuration //配置类
public class RedisConfig {
    @Value("${spring.redis.expire}") //设置Redis缓存的过期时间
    private Long expire;

    /**
     * 配置了一个RedisTemplate,用于与Redis进行数据交互，支持JSON序列化和反序列化
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    //RedisTemplate是Spring Data Redis中用于操作Redis的核心类，提供了丰富的API来进行Redis操作。
    public RedisTemplate<String,Object>redisTemplate(RedisConnectionFactory redisConnectionFactory){
        RedisTemplate<String,Object>template=new RedisTemplate<String ,Object>();
        template.setConnectionFactory((redisConnectionFactory));
        //通过setConnectionFactory方法设置了Redis连接工厂。
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        //使用了Jackson2JsonRedisSerializer作为值（Value）的序列化器，它可以将对象序列化为JSON字符串存储在Redis中。
        //Jackson2JsonRedisSerializer：用于序列化和反序列化 Java 对象为 JSON 字符串。
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //setVisibility 设置 Jackson 对象属性的可见性，使所有属性都可以进行序列化和反序列化。
        objectMapper.activateDefaultTyping(objectMapper.getPolymorphicTypeValidator(),ObjectMapper.DefaultTyping.NON_FINAL);
        //activateDefaultTyping 激活多态类型支持，允许序列化时保留对象的实际类型。
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        //StringRedisSerializer：用于 Redis 键的序列化，因为 Redis 中的键通常是字符串类型。
        template.setKeySerializer(stringRedisSerializer);
        //设置 RedisTemplate 中键的序列化方式。
        template.setHashKeySerializer(stringRedisSerializer);
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //设置 RedisTemplate 中值的序列化方式。
        template.setHashKeySerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();  //初始化
        return template;
    }


    /**
     * 配置了一个RedisCacheManager,用于管理Redis缓存，设置缓存的过期时间，并指定缓冲健和值的序列化方式
     * @param factory
     * @return
     */
    @Bean
    //RedisCacheManager：Spring Data Redis 提供的缓存管理器，负责 Redis 缓存的管理和配置。
    public RedisCacheManager cacheManager(RedisConnectionFactory factory){
        RedisCacheConfiguration cacheConfiguration=RedisCacheConfiguration.defaultCacheConfig();
        //RedisCacheConfiguration.defaultCacheConfig()：获取默认的缓存配置对象。
        cacheConfiguration.entryTtl(Duration.ofMinutes(expire))//设置缓存过期时间
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.string()))
                //serializeKeysWith：设置缓存键的序列化方式，这里使用 StringRedisSerializer 来序列化缓存键。
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.json()));
                //设置缓存值的序列化方式，这里使用 RedisSerializer.json() 来序列化缓存值，即将缓存的值转换为 JSON 格式。
        return RedisCacheManager
                .builder(factory)  //配置连接工厂
                .cacheDefaults(cacheConfiguration)  //配置缓存默认参数
                .build();   //构建缓存管理器

    }

}
